package com.example.invoker.schedule.impl;

import cn.hutool.json.JSONObject;
import com.biapp.appboard.mapper.goveesu.GoveeSuMapper;
import com.biapp.appboard.pojo.constant.AppBoardConstants;
import com.biapp.appboard.pojo.dto.operation.DailyPointsIssuedDTO;
import com.biapp.appboard.pojo.model.appboard.baseinfo.AppTotalValueInfo;
import com.biapp.appboard.pojo.model.appboard.member.AppNewRedemption;
import com.biapp.appboard.pojo.model.operation.AppPointsIssuance;
import com.biapp.appboard.service.appboardservice.baseinfo.AppTotalValueInfoService;
import com.biapp.appboard.service.appboardservice.member.AppNewRedemptionService;
import com.biapp.appboard.service.operation.PointsIssuanceService;
import com.biapp.appboard.service.schedule.BoardSyncScheduleService;
import com.biapp.appboard.service.schedule.flurry.lightingeffect.BestCreatorSyncService;
import com.biapp.appboard.service.schedule.flurry.lightingeffect.LightingEffectSquareSyncService;
import com.biapp.appboard.service.schedule.flurry.lightingeffect.RandomLightingEffectSyncService;
import com.biapp.appboard.service.schedule.flurry.lightingeffect.RecommendedLightingEffectService;
import com.biapp.appboard.service.schedule.flurry.others.ApplyRandomColorSyncService;
import com.biapp.appboard.service.schedule.flurry.others.ImgEffectSyncService;
import com.biapp.appboard.service.schedule.flurry.others.SiriSyncService;
import com.biapp.appboard.service.schedule.flurry.others.SoundLidSyncService;
import com.biapp.common.exception.BizException;
import com.biapp.common.util.HttpUtils;
import com.biapp.common.util.IntegerUtil;
import com.biapp.common.util.ZonedDateUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author caipeng
 * @since 2021-06-09 18:38:03
 */
@Service
public class BoardSyncScheduleServiceImpl implements BoardSyncScheduleService {

    @Autowired
    private GoveeSuMapper goveeSuMapper;

    @Autowired
    private AppTotalValueInfoService appTotalValueInfoService;

    @Autowired
    private PointsIssuanceService pointsIssuanceService;

    @Autowired
    private AppNewRedemptionService appNewRedemptionService;

    @Value("${app.redeem-records.url}")
    private String redeemRecordsUrl;

    @Value("${app.redeem-records.header}")
    private String header;

    @Value("${app.redeem-records.token}")
    private String token;

    @Autowired
    private RandomLightingEffectSyncService randomLightingEffectSyncService;

    @Autowired
    private BestCreatorSyncService bestCreatorSyncService;

    @Autowired
    private RecommendedLightingEffectService recommendedLightingEffectService;

    @Autowired
    private LightingEffectSquareSyncService lightingEffectSquareSyncService;

    @Autowired
    private ApplyRandomColorSyncService applyRandomColorSyncService;

    @Autowired
    private SoundLidSyncService soundLidSyncService;

    @Autowired
    private SiriSyncService siriSyncService;

    @Autowired
    private ImgEffectSyncService imgEffectSyncService;

    /**
     * 统计积分发放数据
     * 1.先统计一下总的积分情况（积分发放总额、活动积分发放总额、非活动积分发放总额）
     * 2.统计前一天的数据
     *
     * @param startDate
     * @param endDate
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncPointsIssuance(String startDate, String endDate) {
        Long startTime = null;
        Long endTime = null;
        if (StringUtils.isAnyBlank(startDate, endDate)) {
            ZonedDateTime yesterday = ZonedDateUtil.today(ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI).plusDays(-1);
            startDate = ZonedDateUtil.convertZoneTimeToStr(yesterday, ZonedDateUtil.dayFormatterStr);
            endDate = ZonedDateUtil.convertZoneTimeToStr(yesterday, ZonedDateUtil.dayFormatterStr);
        }

        startTime = ZonedDateUtil.convertToDate(ZonedDateUtil.toStartOfTheDay(startDate, ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI)).getTime();
        endTime = ZonedDateUtil.convertToDate(ZonedDateUtil.toEndOfTheDay(endDate, ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI)).getTime();

        /*
        1.1 查询积分发放总额
        1.2 查询活动积分发放总额
        1.3 非活动积分 = 积分发放总额 - 活动积分发放总额
         */
        Integer totalPointsIssued = goveeSuMapper.getTotalPointsIssued();

        Integer totalActivityPointsIssued = goveeSuMapper.getTotalActivityPointsIssued();

        Integer totalInactivityPointsIssued = totalPointsIssued - totalActivityPointsIssued;
        // 保存积分发放到表中；2.查询每天的积分发放情况
        List<AppTotalValueInfo> totalValueInfoList = new ArrayList<>();
        AppTotalValueInfo totalPointsIssuedInfo = new AppTotalValueInfo(AppBoardConstants.TOTAL_VALUE_BUSINESS_MODULE_OPERATION_BOARD, AppBoardConstants.TOTAL_VALUE_CATEGORY_POINTS_ISSUANCE, AppBoardConstants.TOTAL_VALUE_KEY_TOTAL_POINTS_ISSUED, totalPointsIssued);
        AppTotalValueInfo totalActivityPointsIssuedInfo = new AppTotalValueInfo(AppBoardConstants.TOTAL_VALUE_BUSINESS_MODULE_OPERATION_BOARD, AppBoardConstants.TOTAL_VALUE_CATEGORY_POINTS_ISSUANCE, AppBoardConstants.TOTAL_VALUE_KEY_ACTIVITY_POINTS_ISSUED, totalActivityPointsIssued);
        AppTotalValueInfo totalInactivityPointsIssuedInfo = new AppTotalValueInfo(AppBoardConstants.TOTAL_VALUE_BUSINESS_MODULE_OPERATION_BOARD, AppBoardConstants.TOTAL_VALUE_CATEGORY_POINTS_ISSUANCE, AppBoardConstants.TOTAL_VALUE_KEY_INACTIVITY_POINTS_ISSUED, totalInactivityPointsIssued);
        totalValueInfoList.add(totalPointsIssuedInfo);
        totalValueInfoList.add(totalActivityPointsIssuedInfo);
        totalValueInfoList.add(totalInactivityPointsIssuedInfo);

        appTotalValueInfoService.updateValue(totalValueInfoList);

        /*
        2
         */
        List<DailyPointsIssuedDTO> totalIssuedList = goveeSuMapper.getDailyTotalPointsIssuedByDateRange(startTime, endTime);
        if (CollectionUtils.isEmpty(totalIssuedList)) {
            return;
        }

        List<DailyPointsIssuedDTO> activityIssuedList = goveeSuMapper.getDailyActivityPointsByDateRange(startTime, endTime);
        if (CollectionUtils.isEmpty(activityIssuedList)) {
            activityIssuedList = Collections.emptyList();
        }

        Map<Integer, Integer> totalIssuedMap = totalIssuedList.stream().collect(Collectors.toMap(DailyPointsIssuedDTO::getDate, DailyPointsIssuedDTO::getPoints));
        Map<Integer, Integer> activityIssuedMap = activityIssuedList.stream().collect(Collectors.toMap(DailyPointsIssuedDTO::getDate, DailyPointsIssuedDTO::getPoints));

        List<AppPointsIssuance> dailyPointIssuedList = new ArrayList<>();
        totalIssuedMap.forEach((k, v) -> {
            Integer dailyActivityIssued = activityIssuedMap.get(k);
            if (dailyActivityIssued == null) {
                dailyActivityIssued = IntegerUtil.ZERO;
            }
            AppPointsIssuance pointsIssuance = new AppPointsIssuance();
            pointsIssuance.setDailyYear(Integer.parseInt(String.valueOf(k).substring(0, 4)));
            pointsIssuance.setDailyMonth(Integer.parseInt(String.valueOf(k).substring(4, 6)));
            pointsIssuance.setDailyWeek(Integer.parseInt(ZonedDateUtil.getWeek(ZonedDateUtil.convertDateIntToStrDate(k)).substring(5)));
            pointsIssuance.setDailyDate(k);
            pointsIssuance.setActivityPointsNum(dailyActivityIssued);
            pointsIssuance.setInactivityPointsNum(v - dailyActivityIssued);
            dailyPointIssuedList.add(pointsIssuance);
        });

        pointsIssuanceService.batchInsert(dailyPointIssuedList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncPrizeDelivery(String startDate, String endDate) {
        Long startTime = null;
        Long endTime = null;
        if (StringUtils.isAnyBlank(startDate, endDate)) {
            ZonedDateTime yesterday = ZonedDateUtil.today(ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI).plusDays(-1);
            startDate = ZonedDateUtil.convertZoneTimeToStr(yesterday, ZonedDateUtil.dayFormatterStr);
            endDate = ZonedDateUtil.convertZoneTimeToStr(yesterday, ZonedDateUtil.dayFormatterStr);
        }

        int intStart = Integer.parseInt(startDate.replaceAll("-", ""));
        int intEnd = Integer.parseInt(endDate.replaceAll("-", ""));
        int daysDiff = ZonedDateUtil.daysBetween(ZonedDateUtil.convertStrToDate(startDate, ZonedDateUtil.dayFormatterStr), ZonedDateUtil.convertStrToDate(endDate, ZonedDateUtil.dayFormatterStr));
        List<AppNewRedemption> redemptionList = new ArrayList<>();
        for (int i = 0; i <= daysDiff; i++) {
            String newDate = ZonedDateUtil.convertZoneTimeToStr(ZonedDateUtil.convertDateStrToZonedDateTime(ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI, ZonedDateUtil.convertDateIntToStrDate(intStart)).plusDays(Long.parseLong(String.valueOf(i))), ZonedDateUtil.dayFormatterStr);
            startTime = ZonedDateUtil.convertToDate(ZonedDateUtil.toStartOfTheDay(newDate, ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI)).getTime();
            endTime = ZonedDateUtil.convertToDate(ZonedDateUtil.toEndOfTheDay(newDate, ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI)).getTime();

            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("state", 1);
            paramsMap.put("issuanceType", 1);
            paramsMap.put("startTime", startTime);
            paramsMap.put("endTime", endTime);
            paramsMap.put("pageSize", 15);
            paramsMap.put("pageNum", 1);

            Map<String, String> headerMap = new HashMap<>();
            headerMap.put(header, token);
            String resultStr = null;
            try {
                resultStr = HttpUtils.get(redeemRecordsUrl, headerMap, paramsMap);
            } catch (Exception e) {
                e.printStackTrace();
                throw new BizException(1, "同步奖品发放数据请求异常");
            }

            JSONObject resultJson = new JSONObject(resultStr);
            Integer total = new JSONObject(resultJson.getStr("data")).getInt("total");
            AppNewRedemption appNewRedemption = new AppNewRedemption();
            appNewRedemption.setDailyDate(Integer.parseInt(newDate.replaceAll("-", "")));
            appNewRedemption.setPrizeDeliveryNum(total);
            redemptionList.add(appNewRedemption);
        }
        appNewRedemptionService.syncPrizeDelivery(redemptionList);
    }

    /**
     * 同步灯效广场数据
     *
     * @param startDate
     * @param endDate
     */
    @Override
    public void syncLightEffect(String startDate, String endDate) {
        if (StringUtils.isAnyBlank(startDate, endDate)) {
            ZonedDateTime yesterday = ZonedDateUtil.today(ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI).plusDays(-1);
            startDate = ZonedDateUtil.convertZoneTimeToStr(yesterday, ZonedDateUtil.dayFormatterStr);
            endDate = ZonedDateUtil.convertZoneTimeToStr(yesterday, ZonedDateUtil.dayFormatterStr);
        }

        // 调用Flurry接口需要+1天
        String newEndDate = ZonedDateUtil.convertZoneTimeToStr(ZonedDateUtil.convertDateStrToZonedDateTime(ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI, endDate).plusDays(1), ZonedDateUtil.dayFormatterStr);
        randomLightingEffectSyncService.process(startDate, newEndDate);
        bestCreatorSyncService.process(startDate, newEndDate);
        recommendedLightingEffectService.process(startDate, newEndDate);
        lightingEffectSquareSyncService.process(startDate, newEndDate);

    }

    @Override
    public void syncOtherTimes(String startDate, String endDate) {
        if (StringUtils.isAnyBlank(startDate, endDate)) {
            ZonedDateTime yesterday = ZonedDateUtil.today(ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI).plusDays(-1);
            startDate = ZonedDateUtil.convertZoneTimeToStr(yesterday, ZonedDateUtil.dayFormatterStr);
            endDate = ZonedDateUtil.convertZoneTimeToStr(yesterday, ZonedDateUtil.dayFormatterStr);
        }

        // 调用Flurry接口需要+1天
        String newEndDate = ZonedDateUtil.convertZoneTimeToStr(ZonedDateUtil.convertDateStrToZonedDateTime(ZonedDateUtil.TIMEZONE_ASIN_SHANGHAI, endDate).plusDays(1), ZonedDateUtil.dayFormatterStr);

        applyRandomColorSyncService.process(startDate, newEndDate);
        soundLidSyncService.process(startDate, newEndDate);
        siriSyncService.process(startDate, newEndDate);
        imgEffectSyncService.process(startDate, newEndDate);
    }

}
